package com.joymart.common.utils;
import lombok.SneakyThrows;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.function.Function;


public abstract class ExcelExporter<T> {

    /**
     * 导出 Excel 文件为字节数组
     * @param data 数据列表，每个元素渲染为一行
     * @param rowMapper 渲染逻辑，定义如何将元素的属性映射到列值
     * @return 包含 Excel 数据的字节数组
     * @throws IOException 如果文件写入失败
     */
    @SneakyThrows
    public byte[] exportToExcel(List<T> data, Function<T, List<Object>> rowMapper) throws IOException {
        // 创建工作簿和工作表
        try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            Sheet sheet = workbook.createSheet(getSheetName());

            // 创建表头
            createHeader(sheet, workbook);

            // 填充数据行
            int rowIndex = 1; // 数据行从第 2 行开始

            for (T item : data) {
                Row row = sheet.createRow(rowIndex++);
                List<Object> rowData = rowMapper.apply(item);
                for (int colIndex = 0; colIndex < rowData.size(); colIndex++) {
                    Object value = rowData.get(colIndex);
                    Cell cell = row.createCell(colIndex);
                    setCellValue(cell, value);
                }
            }

            // 自动调整列宽
            autoSizeColumns(sheet);

            // 写入到字节数组输出流
            workbook.write(baos);
            return baos.toByteArray();
        }
    }

    /**
     * 获取工作表名称，子类可自定义实现
     * @return 工作表名称
     */
    protected abstract String getSheetName();

    protected abstract List<String> getHeaders();

    /**
     * 自动调整列宽
     * @param sheet 工作表对象
     */
    private void autoSizeColumns(Sheet sheet) {
        int numberOfColumns = sheet.getRow(0).getPhysicalNumberOfCells();
        for (int i = 0; i < numberOfColumns; i++) {
            sheet.autoSizeColumn(i);
            // 手动调整列宽，以适应中文
            int width = sheet.getColumnWidth(i);
            // 增加一定的宽度，以适应中文字符
            sheet.setColumnWidth(i, width * 2); // 调整倍数根据实际需求可以修改
        }
    }

    /**
     * 根据对象类型设置单元格的值和类型
     * @param cell 单元格对象
     * @param value 单元格的值
     */
    private void setCellValue(Cell cell, Object value) {
        if (value == null) {
            cell.setCellType(CellType.BLANK);
        } else if (value instanceof String) {
            cell.setCellValue((String) value);
        } else if (value instanceof Integer) {
            cell.setCellValue((Integer) value);
        } else if (value instanceof BigDecimal) {
            cell.setCellValue(((BigDecimal) value).doubleValue());
        } else if (value instanceof LocalDateTime) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            cell.setCellValue(((LocalDateTime) value).format(formatter));
        } else if (value instanceof Double) {
            cell.setCellValue((Double) value);
        } else if (value instanceof Boolean) {
            cell.setCellValue((Boolean) value);
        } else {
            cell.setCellValue(value.toString());
        }
    }

    // 示例用法
    private void createHeader(Sheet sheet, Workbook workbook) {
        Row headerRow = sheet.createRow(0);
        CellStyle headerStyle = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setBold(true);
        headerStyle.setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex());
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        headerStyle.setFont(font);

        List<String> headers = getHeaders();
        for (int i = 0; i < headers.size(); i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers.get(i));
            cell.setCellStyle(headerStyle);
        }
    }
}
